#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <list>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "Log.hpp"
#include "InetAddr.hpp"
#include "Mutex.hpp"
#include<algorithm>
using namespace LogModule;
using namespace LockModule;
class UserInterface
{
public:
    virtual ~UserInterface() = default;
    virtual void SendTo(int sockfd, const std::string &message) = 0;
    virtual bool operator==(const InetAddr &u) const = 0;
    virtual std::string Id() = 0;
};

// 先描述用户
class User : public UserInterface
{
public:
    User(InetAddr id)
        : _id(id)
    {
    }
    void SendTo(int sockfd, const std::string &message) override
    {
        sendto(sockfd, message.c_str(), message.size(), 0, _id.NetAddr(), _id.NetAddrLen());
        LOG(LogLevel::DEBUG) << "send message to " << _id.Addr() << " info is " << message << "\n";
    }
    bool operator==(const User &u) const
    {
        return u._id == _id;
    }
    bool operator==(const InetAddr &u) const
    {
        return u == _id;
    }
    std::string Id()
    {
        return _id.Addr();
    }
    ~User() {}

private:
    InetAddr _id;
};
// 再组织用户
// 把消息进行路由，要把用户全部管理起来
class UserManager
{
public:
    UserManager() {}
    ~UserManager() {}
    void AddUser(InetAddr &user)
    {
        LockGuard lockguard(_mutex);
        for (auto &item : _online_user)
            if (*item == user)
            {
                LOG(LogLevel::DEBUG) << user.Addr() << "已经存在";
                return;
            }
        _online_user.push_back(std::make_shared<User>(user));
        LOG(LogLevel::DEBUG) << "add user " << user.Addr();
        ;
    }
    void DeleteUser(InetAddr &id)
    {
        auto pos = remove_if(_online_user.begin(), _online_user.end(), [&](std::shared_ptr<UserInterface> user)
                                  { return *user == id; });
        _online_user.erase(pos, _online_user.end());
        PrintUser();
    }
    void Router(int sockfd, const std::string &message)
    {
        LockGuard lockguard(_mutex);
        for (auto &user : _online_user)
        {
            user->SendTo(sockfd, message);
        }
    }
    void PrintUser()
    {
        for (auto &item : _online_user)
        {
            LOG(LogLevel::DEBUG) << "在线用户" << item->Id();
        }
    }

private:
    std::list<std::shared_ptr<UserInterface>> _online_user; // 在线用户
    Mutex _mutex;
};